package com.itheima.stock.service.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.common.domain.*;
import com.itheima.stock.common.enums.ResponseCode;
import com.itheima.stock.config.StockInfoConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author byzhao
 * @version 1.0
 * @description 股票业务实现类
 * @date 2022/10/12 16:05:18
 */
@Service
@Slf4j
public class StockServiceImpl implements StockService {
    //1 涨停  0跌停
    private static final int UP = 1;
    private static final int DOWN = 0;
    private static final int START_PAGE = 1;
    private static final int PAGE_SIZE = 20;
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;


    /**
     * 获取所有股票主营业务数据
     *
     * @return
     */
    @Override
    public List<StockBusiness> getAllStockBusiness() {
        // 1. 参数校验

        // 2. 核心业务逻辑
        List<StockBusiness> stockBusinessList = stockBusinessMapper.selectAll();

        // 3. 数据封装

        return stockBusinessList;
    }

    /**
     * 获取大盘数据
     *
     * @return
     */
    @Override
    public R<List<InnerMarketDomain>> innerIndexAll() {

        //参数校验

        //核心业务
        //获取有效交易时间
        Date date = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //TODO mock数据
        String mockDate = "20211226105600";//TODO 后续大盘数据实时拉去，将该行注释掉 传入的日期秒必须为0
        date = DateTime.parse(mockDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //国内大盘指数id
        List<String> innerIds = stockInfoConfig.getInner();
        List<InnerMarketDomain> innerMarketDomains = stockMarketIndexInfoMapper.selectByIdsAndDate(innerIds, date);
        //数据封装
        for (InnerMarketDomain innerMarketDomain : innerMarketDomains) {
            innerMarketDomain.setCurDate(DateTime.parse(innerMarketDomain.getCurDate(),DateTimeFormat.forPattern("yyyyMMdd")).toString("yyyy/MM/dd"));
        }
        if (CollectionUtils.isEmpty(innerMarketDomains)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(innerMarketDomains);
    }

    /**
     * 外盘指数
     * @return
     */
    @Override
    public R<List<OuterMarketDomain>> externalIndex() {

        //参数校验

        //核心业务
        //获取有效交易时间
        Date date = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //TODO mock数据
        String mockDate = "20220102120000";//TODO 后续大盘数据实时拉去，将该行注释掉 传入的日期秒必须为0
        date = DateTime.parse(mockDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<String> outer = stockInfoConfig.getOuter();
        List<OuterMarketDomain> outerMarketDomains = stockMarketIndexInfoMapper.selectExternalIndex(outer,date);

        //数据封装

        return R.ok(outerMarketDomains);
    }

    /**
     * 板块指数
     *
     * @return
     */
    @Override
    public R<List<StockBlockRtInfoDomain>> sectorAllLimit() {

        //参数校验

        //核心业务
        List<StockBlockRtInfoDomain> stockBlockRtInfoDomains = stockBlockRtInfoMapper.sectorAllLimit();
        for (StockBlockRtInfoDomain stockBlockRtInfo : stockBlockRtInfoDomains) {
            stockBlockRtInfo.setCurDate(DateTime.parse(stockBlockRtInfo.getCurDate(),DateTimeFormat.forPattern("yyyyMMdd")).toString("yyyy/MM/dd"));
        }
        //数据封装
        if (CollectionUtils.isEmpty(stockBlockRtInfoDomains)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(stockBlockRtInfoDomains);
    }

    /**
     * 涨幅榜
     *
     * @return
     */
    @Override
    public R<List<StockUpDownCountDomain>> stockIncreaseLimit() {

        //参数校验

        //核心业务
        //获取当前时间
        Date date = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //TODO mock数据
        String mockStr = "2021-12-30 09:42:00";
        Date date1 = DateTime.parse(mockStr, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        List<StockUpDownCountDomain> stockUpDownCountDomains = stockRtInfoMapper.stockIncreaseLimit(date1);
        //数据封装
        for (StockUpDownCountDomain stockUpDownCountDomain : stockUpDownCountDomains) {
            stockUpDownCountDomain.setCurDate(DateTime.parse(stockUpDownCountDomain.getCurDate(), DateTimeFormat.forPattern("yyyyMMdd")).toString("yyyy/MM/dd"));

        }
        stockUpDownCountDomains = stockUpDownCountDomains.stream().map((s) -> {
            BigDecimal upDown = s.getUpDown();
            BigDecimal bigDecimal = new BigDecimal(100);
            s.setUpDown(upDown.multiply(bigDecimal));
            String name = s.getName();
            s.setName(name.replace("\"", ""));
            return s;
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(stockUpDownCountDomains)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(stockUpDownCountDomains);
    }

    /**
     * 涨幅榜查看更多
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public R<PageResult<StockUpDownCountDomain>> stockAllPage(Integer page, Integer pageSize) {

        //参数校验
        if (page == null || pageSize == null || page <= 0 || pageSize <= 0) {
            page = 1;
            pageSize = 20;
        }
        //核心业务
        PageHelper.startPage(page, pageSize);
        List<StockUpDownCountDomain> stockUpDownCountDomains = stockRtInfoMapper.selectStockAll();
        PageInfo<StockUpDownCountDomain> pageInfo = PageInfo.of(stockUpDownCountDomains);
        //数据封装
        stockUpDownCountDomains = stockUpDownCountDomains.stream().map((s) -> {
            BigDecimal upDown = s.getUpDown();
            BigDecimal bigDecimal = new BigDecimal(100);
            s.setUpDown(upDown.multiply(bigDecimal));
            String name = s.getName();
            s.setName(name.replace("\"", ""));
            return s;
        }).collect(Collectors.toList());
        PageResult<StockUpDownCountDomain> build = PageResult.<StockUpDownCountDomain>builder()
                .pageNum(page)
                .pageSize(pageSize)
                .totalRows(pageInfo.getTotal())
                //.totalPages(pageInfo.getPages())
                .totalPages((int) pageInfo.getTotal())
                .size(pageInfo.getSize())
                .rows(stockUpDownCountDomains).build();
        return R.ok(build);
    }

    /**
     * 涨停跌停数据统计
     *
     * @return
     */
    @Override
    public R<Map> stockUpDownCount() {

        //参数校验

        //核心业务
        //获取股票最近的有效交易日期,精确到秒
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //当前最近有效期
        Date dateTime = curDateTime.toDate();
        //开盘日期
        Date openTime = DateTimeUtil.getOpenDate(curDateTime).toDate();
        String timeStr = "20220106142500";
        String openTimeStr = "20220106092500";
        dateTime = DateTime.parse(timeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        openTime = DateTime.parse(openTimeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<Map> upList = stockRtInfoMapper.selectStockUpDownCount(dateTime, openTime, UP);
        List<Map> downList = stockRtInfoMapper.selectStockUpDownCount(dateTime, openTime, DOWN);
        //数据封装
        HashMap<String, List<Map>> map = new HashMap<>();
        map.put("upList", upList);
        map.put("downList", downList);
        return R.ok(map);
    }

    /**
     * 将指定页的股票数据导出到excel
     *
     * @param page
     * @param pageSize
     */
    @Override
    public List<StockExcelDomain> stockExport(Integer page, Integer pageSize) {
        //参数校验
        if (Objects.isNull(page)
                || Objects.isNull(pageSize)
                || page <= 0
                || pageSize <= 0) {
            page = START_PAGE;
            pageSize = PAGE_SIZE;
        }

        //核心业务
        PageHelper.startPage(page, pageSize);
        List<StockUpDownCountDomain> infos = stockRtInfoMapper.selectStockAll();
        //数据封装
        //Gson gson = new Gson();
        List<StockExcelDomain> excelDomains = infos.stream().map(info -> {
            StockExcelDomain domain = new StockExcelDomain();
            BeanUtils.copyProperties(info, domain);
            return domain;
        }).collect(Collectors.toList());

        return excelDomains;
    }

    /**
     * 统计国内A股大盘T日和T-1日成交量对比
     *
     * @return
     */
    @Override
    public R<StockTradevolDomain> stockTradevol() {

        //参数校验

        //核心业务
        //1.获取最近的股票交易日时间，精确到分钟 T交易日
        DateTime tDate = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date tDateTime = tDate.toDate();
        //对应的开盘时间
        Date tOpenTime = DateTimeUtil.getOpenDate(tDate).toDate();
        //TODO 后续注释掉 mock-data
        String tDateStr = "20220103143000";
        tDateTime = DateTime.parse(tDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //mock-data
        String openDateStr = "20220103093000";
        tOpenTime = DateTime.parse(openDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //获取T-1交易日
        DateTime preTDate = DateTimeUtil.getPreviousTradingDay(tDate);
        Date preTTime = preTDate.toDate();
        Date preTOpenTime = DateTimeUtil.getOpenDate(preTDate).toDate();
        //TODO 后续注释掉 mock-data
        String preTStr = "20220102143000";
        preTTime = DateTime.parse(preTStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //mock-data
        String openDateStr2 = "20220102093000";
        preTOpenTime = DateTime.parse(openDateStr2, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<Vol> volList = stockMarketIndexInfoMapper.selectStockTradevolCount(stockInfoConfig.getInner(), tDateTime, tOpenTime);
        List<Vol> yesVolList = stockMarketIndexInfoMapper.selectStockTradevolCount(stockInfoConfig.getInner(), preTTime, preTOpenTime);
        //日期格式化
        for (Vol vol : volList) {
            vol.setTime(DateTime.parse(vol.getTime(), DateTimeFormat.forPattern("yyyyMMddHHmm")).toString("yyyy-MM-dd HH:mm"));
        }
        for (Vol vol : yesVolList) {
            vol.setTime(DateTime.parse(vol.getTime(), DateTimeFormat.forPattern("yyyyMMddHHmm")).toString("yyyy-MM-dd HH:mm"));
        }
        //数据封装
        StockTradevolDomain stockTradevolDomain = new StockTradevolDomain();
        stockTradevolDomain.setVolList(volList);
        stockTradevolDomain.setYesVolList(yesVolList);
        return R.ok(stockTradevolDomain);
    }

    /**
     * 个股涨跌幅度区间统计
     *
     * @return
     */
    @Override
    public R<StockUpDownDomain> stockUpDown() {

        //参数校验

        //核心业务
        //1.获取当前时间下最近的一个股票交易时间 精确到秒
        DateTime avlDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date time = avlDateTime.toDate();
        //TODO 后续删除 mock-data
        String t = "20220106095500";
        time = DateTime.parse(t, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<Info> infos = stockRtInfoMapper.stockUpDown(time);
        //数据封装
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
        List<Info> sortInfo = upDownRange.stream().map(key -> {
            Optional<Info> title = infos.stream().filter(map -> key.equals(map.getTitle())).findFirst();
            //判断对应的map是否存在
            Info tmp = null;
            if (title.isPresent()) {
                tmp = title.get();
            } else {
                tmp = new Info();
                tmp.setTitle(key);
                tmp.setCount(0L);
            }
            return tmp;
        }).collect(Collectors.toList());
        StockUpDownDomain stock = new StockUpDownDomain();
        stock.setTime(avlDateTime.toString("yyyy-MM-dd HH:mm:ss"));
        stock.setInfos(sortInfo);
        return R.ok(stock);
    }

    /**
     * 个股分时K线行情
     * @param code
     * @return
     */
    @Override
    public R<List<Stock4MinuteDomain>> stockScreenTimesharing(String code) {

        //参数校验
        if(Objects.isNull(code)){
            log.info("查询有误");
        }
        //核心业务
        //1.获取最近有效的股票交易时间
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取当前日期
        Date curDate = curDateTime.toDate();
        //获取当前日期对应的开盘日期
        Date openDate = DateTimeUtil.getOpenDate(curDateTime).toDate();
        //TODO 后续删除 mock-data
        String mockDate="20220106142500";
        curDate=DateTime.parse(mockDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDateStr="20220106093000";
        openDate=DateTime.parse(openDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<Stock4MinuteDomain> minuteDomainList= stockRtInfoMapper.stockScreenTimesharing(code,openDate,curDate);
        //数据封装

        return R.ok(minuteDomainList);
    }

    /**
     * 个股日k
     * @param code
     * @return
     */
    @Override
    public R<List<Stock4EvrDayDomain>> stockScreenDkline(String code) {

        //参数校验

        //核心业务
        //获取当前日期前推20天
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //当前时间节点
        Date curTime = curDateTime.toDate();
        //前推20
        Date pre20Day = curDateTime.minusDays(20).toDate();

        //TODO 后续删除
        String avlDate="20220106142500";
        curTime=DateTime.parse(avlDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDate="20220101093000";
        pre20Day=DateTime.parse(openDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<Date> dateList = stockRtInfoMapper.stockScreenDayDate(code,pre20Day, curTime);
        //List<Stock4EvrDayDomain> stock4EvrDayDomains = stockRtInfoMapper.stockScreenDkline(code,pre20Day,curTime);
        List<Stock4EvrDayDomain> stock4EvrDayDomains = stockRtInfoMapper.stockScreenDkline(code,dateList);
        //数据封装
        return R.ok(stock4EvrDayDomains);
    }

    /**
     * 周k
     * @param code
     * @return
     */
    @Override
    public R<List<Stock4WeekDomain>> StockScreenWeekKline(String code) {

        //参数校验

        //核心业务
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //当前时间节点
        Date curTime = curDateTime.toDate();
        //前推
        Date preDay = curDateTime.minusDays(20).toDate();

        //TODO 后续删除
        String avlDate="20220107143000";
        curTime=DateTime.parse(avlDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDate="20211219093000";
        preDay=DateTime.parse(openDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        List<Stock4WeekDomain> stock4WeekDomains = stockRtInfoMapper.stockScreenWeekKline(code,preDay,curTime);
        //数据封装
        return R.ok(stock4WeekDomains);

    }
}
